package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.enums.LocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description DeviceSeviceImpl
 * @Author xiaoyang
 * @Date 2025/9/10 15:41
 */

@Slf4j
@Service
public class DeviceSeviceImpl implements DeviceService {

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private Client client;

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() {
        QueryProductListRequest queryProductListRequest = new QueryProductListRequest();
        queryProductListRequest.setCurrentPage(1);
        queryProductListRequest.setPageSize(200);
        queryProductListRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryProductListResponse queryProductListResponse = null;
        try {
            queryProductListResponse = client.queryProductList(queryProductListRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }

        if (!queryProductListResponse.getBody().getSuccess()) throw new RuntimeException(queryProductListResponse.getBody().getErrorMessage());

        List<ProductVo> productVoList = queryProductListResponse.getBody().getData().getList().getProductInfo()
                .stream().map(productInfo -> BeanUtil.toBean(productInfo, ProductVo.class))
                .collect(Collectors.toList());

        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));
    }

    @Override
    public List<ProductVo> allProduct() {
        String productList = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        if (ObjectUtil.isEmpty(productList)) return Collections.EMPTY_LIST;
        return JSONUtil.toList(productList, ProductVo.class);
    }

    @Override
    public void RegisterDevice(DeviceDto deviceDto) {
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0) throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);

        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());


        RegisterDeviceResponse registerDeviceResponse = null;
        try {
             registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        if (!registerDeviceResponse.getBody().getSuccess()) throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        log.info("设备: {} 注册成功",registerDeviceResponse.getBody().getData().getDeviceName());

        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(registerDeviceResponse.getBody().getData().getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryProductResponse.getBody().getSuccess()) throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(registerDeviceResponse.getBody().getData().getIotId());
        device.setProductName(queryProductResponse.getBody().getData().getProductName());
        if (device.getLocationType().equals(LocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        deviceMapper.insertSelective(device);
    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        Page<DeviceVo> deviceVos = deviceMapper.pageQueryDevice(devicePageQueryDto);
        return PageResponse.of(deviceVos, DeviceVo.class);
    }

    @Override
    public DeviceVo QueryDeviceDetail(QueryDeviceDetailRequest queryDeviceDetailRequest) {
        queryDeviceDetailRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse queryDeviceDetailResponse = null;
        try {
            queryDeviceDetailResponse = client.queryDeviceDetail(queryDeviceDetailRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_SERVICE_DATA_ERROR);
        }
        if (!queryDeviceDetailResponse.getBody().getSuccess()) throw new RuntimeException(queryDeviceDetailResponse.getBody().getErrorMessage());

        DeviceVo deviceVo = deviceMapper.selectByIotId(queryDeviceDetailRequest.getIotId());

        BeanUtils.copyProperties(queryDeviceDetailResponse.getBody().getData(), deviceVo);

        return deviceVo;
    }

    @Override
    public QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData QueryThingModelPublished(QueryThingModelPublishedRequest queryThingModelPublishedRequest) {
        queryThingModelPublishedRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse queryThingModelPublishedResponse = null;

        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(queryThingModelPublishedRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        if (!queryThingModelPublishedResponse.getBody().getSuccess()) throw new RuntimeException(queryThingModelPublishedResponse.getBody().getErrorMessage());

        return queryThingModelPublishedResponse.getBody().getData();
    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        if (ObjectUtil.isEmpty(deviceMapper.selectById(deviceDto.getId()))) throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        deviceMapper.updateByPrimaryKeySelective(BeanUtil.toBean(deviceDto, Device.class));


        BatchUpdateDeviceNicknameRequest batchUpdateDeviceNicknameRequest = new BatchUpdateDeviceNicknameRequest();
        batchUpdateDeviceNicknameRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        batchUpdateDeviceNicknameRequest.setDeviceNicknameInfo(Lists.newArrayList(deviceNicknameInfo));
        BatchUpdateDeviceNicknameResponse batchUpdateDeviceNicknameResponse = null;
        try {
            batchUpdateDeviceNicknameResponse = client.batchUpdateDeviceNickname(batchUpdateDeviceNicknameRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (!batchUpdateDeviceNicknameResponse.getBody().getSuccess()) throw new RuntimeException(batchUpdateDeviceNicknameResponse.getBody().getErrorMessage());
        log.info("设备: {} 更新成功",deviceDto.getIotId());

    }

    @Override
    public void deleteDevice(DeleteDeviceRequest deleteDeviceRequest) {
        if (ObjectUtil.isEmpty(deviceMapper.selectByIotId(deleteDeviceRequest.getIotId()))) throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        deviceMapper.deleteByIotId(deleteDeviceRequest.getIotId());

        deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse deleteDeviceResponse = null;
        try {
            deleteDeviceResponse = client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!deleteDeviceResponse.getBody().getSuccess()) throw new RuntimeException(deleteDeviceResponse.getBody().getErrorMessage());
        log.info("设备: {} 删除成功",deleteDeviceRequest.getIotId());
    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(QueryDevicePropertyStatusRequest queryDevicePropertyStatusRequest) {
        queryDevicePropertyStatusRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse = null;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(queryDevicePropertyStatusRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        if (!queryDevicePropertyStatusResponse.getBody().getSuccess()) throw new RuntimeException(queryDevicePropertyStatusResponse.getBody().getErrorMessage());

        return queryDevicePropertyStatusResponse.getBody().getData();
    }
}
